package model;

import java.util.ArrayList;
import java.util.Random;

import typesEnum.Statut;
import etresVivant.Fourmi;
import etresVivant.Proie;

/**
 * Classe publique statique:
 * 	- accessible depuis tout le programme
 * 	- aucune instance : on initialise une fois seulement le terrain.
 * 
 * le terrain contient les fourmilieres, les proies et les pheromones
 * c'est le point d'acces du Model.
 */
public class Terrain {
	public static ArrayList<Fourmiliere> fourmilieres;
	public static ArrayList<Proie> proies;
	
	private static boolean bAvailable = false;
	private static int nbColumn, nbLine;
	private static int nbProies;

	private static Case cases[][];

	/* Getter & Setter */
	public static int getNbLine() {
		return nbLine;
	}

	public static int getNbColumn() {
		return nbColumn;
	}

	public static boolean isAvailable() {
		return bAvailable;
	}
	
	// Accesseur pratique pour les cases du terrain
	public static Case getCase(int x, int y) {
		return cases[x][y];
	}
	
	private static Case getRandomCase() {
		Random r = new Random();
		int x, y;
		x = r.nextInt(nbColumn);
		y = r.nextInt(nbLine);
		return Terrain.getCase(x, y);
		
	}
	
	/* Gestion des proies */
	public static void removeProie( Case c ) {
		proies.remove( c.getProie() );
		genProie();
		
		// au cas ou
		if ( proies.isEmpty() ) {
			libererLeKraken(nbProies);
		}
	}
	
	// genere une proie et l'ajoute au terrain
	public static void genProie() {
		boolean bGen = false;
		Case c = null;
		
		// on recupere une case non prise par une autre proie
		while ( !bGen ) {
			c = getRandomCase();
			if ( !c.isProie() ) {
				bGen = true;
			}
		}
		
		Proie p = new Proie( c, Statut.VIVANT );
		c.setProie(true);
		c.setProieLibre(p);
		Terrain.proies.add( p );
	}
	
	private static void libererLeKraken( int nb ) {
		for ( int i = 0; i < nb; i++) {
			genProie();
		}
		
	}

	/**
	 * Initialise le terrain une fois.
	 * 
	 * Si carte non-initialisee :
	 * 	- genere une map + ses cases + les proies + une reine
	 * 	- enfin lance la vie. 
	 */
	public static void init(int nbLignes, int nbCol, int _nbProies ) {
		if (!isAvailable()) { // si le terrain n'a pas ete initialise
			fourmilieres = new ArrayList<Fourmiliere>();
			proies = new ArrayList<Proie>();
			nbColumn = nbCol;
			nbLine = nbLignes;
			nbProies = _nbProies;

			// init des cases
			cases = new Case[nbColumn][nbLine];
			for (int y = 0; y < Terrain.nbLine; y++) { // lignes
				for (int x = 0; x < Terrain.nbColumn; x++) { // colonnes
					cases[x][y] = new Case( x, y );
				}
			}
			System.out.println("...terrain generated");
			
			// 1ere reine + fourmiliere
			Case c = new Case(Terrain.getNbColumn() / 2, Terrain.getNbLine() / 2 );
			/*Fourmi queenElizabou = */Fourmi.newReine(c);
			
			// genere proies
			libererLeKraken( nbProies );			
			System.out.println("...prey generated");
			
			// lance la vie
			for ( Fourmiliere f : fourmilieres ) {
				f.activerVie();
			}
			System.out.println("\n...started life");
			setAvailable(true);
		}
	}
	
	/**
	 * Balaye toutes les cases du terrain en diminuant l'intensité 
	 * des différents types de phéromones si elles existent
	 * Retourne si il y a ou non des pheromones.
	 */
	public static boolean degraderPheromones(){
		boolean bPheromone = false; // aucune pheromones
		
		for(int j =0; j<Terrain.getNbLine(); j++){ 		// Y
			for(int i=0; i<Terrain.getNbColumn(); i++){	// X
				int pheromoneChasse = Terrain.getCase(i, j).getPheromoneChasse();
				int pheromoneReproduction = Terrain.getCase(i, j).getPheromoneReproduction();
				
				// ? il y a des pheromones de chasse
				if (pheromoneChasse > 0) {
					Terrain.getCase(i, j).setPheromoneChasse(pheromoneChasse - 20);
					bPheromone = true;
				}
				
				// ? il y a des pheromones de reproduction
				if (pheromoneReproduction > 0) {
					Terrain.getCase(i, j).setPheromoneReproduction(pheromoneReproduction - 15 );
					bPheromone = true;
				}
			}
		}
		return bPheromone;
	}

	public static void setAvailable(boolean bAvailable) {
		Terrain.bAvailable = bAvailable;
	}
}
